home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
002
/
fspool.arc
/
FSPOOL.ASM
next >
Wrap
Assembly Source File
|
1985-07-09
|
12KB
|
352 lines
PAGE 60,132
TITLE SPOOL - SPOOL PRINTER TO DISK
COMMENT *
SPOOL: THIS DOS COMMAND SPOOLS EVERYTHING WHICH GOES TO THE
PARALLEL PRINTER TO A DISK FILE. DATA IS COLLECTED UNTIL
A SECOND SPOOL COMMAND IS ISSUED.
FORMAT:
SPOOL <FILENAME>
IF NO <FILENAME> IS GIVEN, THE PREVIOUS FILE IS
CLOSED AND ALL FURTHER PRINTER DATA GOES TO THE
PRINTER.
PROGRAMMER: DON D WORTH - UCLA/OAC - 1/5/84
ENTRY POINTS: +100 = STANDARD INITIAL COMMAND ENTRY
+103 = PRINTER INTERRUPT ENTRY POINT
TO LINK: LINK SPOOL,SPOOL,SPOOL;
DEBUG SPOOL.EXE
N SPOOL.COM
W
Q
*
BUFSIZ EQU 200H ;SIZE OF DMA BUFFER
;
CONOUT EQU 02H ; CONSOLE OUTPUT
PRINT EQU 09H ; PRINT STRING
OPEN EQU 0FH ; OPEN FILE
CLOSE EQU 10H ; CLOSE FILE
DELETE EQU 13H ; DELETE FILE
MAKE EQU 16H ; MAKE FILE
SETDMA EQU 1AH ; SET DMA ADDRESS
WRITER EQU 22H ; RANDOM WRITE
GETDMA EQU 2FH ; GET DMA ADDRESS
;
BELL EQU 07H ;BELL
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
SPACE EQU 20H ;SPACE
;
PGM GROUP ASEG,CSEG,DSEG
ASSUME CS:PGM,DS:PGM
;
; PREFIX SEGMENT
;
ASEG SEGMENT PARA COMMON 'CODE'
INT20 LABEL NEAR
DW ?
MEMSIZ DW ? ;TOTAL MEMORY SIZE
DB ?
BDOS LABEL NEAR
DB 5 DUP(?) ;LONG CALL TO DOS
TERMAD DW ?,? ;TERMINATE ADDRESS
CTLBRK DW ?,? ;CONTROL-BREAK EXIT
DW 37 DUP(?) ;RESERVED
FCB1 DB 16 DUP(?) ;FIRST FCB
FCB2 DB 16 DUP(?) ;SECOND FCB
DW ?,? ;RESERVED
DMA DB 128 DUP(?) ;DMA SECTOR BUFFER
;
ASEG ENDS
;
; DATA SEGMENT
;
DSEG SEGMENT PARA PUBLIC 'DATA'
;
MSG DB CR,LF,'SPOOL INSTALLED',CR,LF,'$'
MSGOPN DB CR,LF,'NO ROOM IN DIRECTORY FOR SPOOL FILE',BELL,CR,LF,'$'
;
DSEG ENDS
;
; START OF CODE
;
CSEG SEGMENT PARA PUBLIC 'CODE'
;
; NORMAL COMMAND ENTRY
;
SPOOL: JMP INIT ;GO TO INIT CODE
;
; PARALLEL PRINTER INTERRUPT EXIT - INT 17H
;
INTENT: STI ;INTERRUPTS BACK ON
PUSH DS
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH AX
MOV SI,CS
MOV DS,SI ;SET UP DATA SEGMENT
CMP BYTE PTR FLAG,0 ;IS FILE AVAILABLE?
JNZ MYINT ;YES, GO ON
POP AX
POP DI
POP SI
POP DX
POP CX
POP BX
POP DS
JMP DWORD PTR CS:VEC ;ELSE, GO TO REAL EXIT
;
MYINT: OR AH,AH ;AH=0 : PRINT CHARACTER IN AL
JNZ INTEXT
MOV SI,SS
MOV WORD PTR STKSAV+2,SI ;SAVE CALLER'S STACK
MOV SI,SP
MOV WORD PTR STKSAV,SI
MOV SI,CS
MOV SS,SI ;GIVE ME NEW BIGGER STACK
MOV SI,OFFSET PGM:STK
MOV SP,SI
CALL PRNT ;PRINT THE CHARACTER
MOV SI,WORD PTR STKSAV
MOV SP,SI ;RESTORE CALLER'S STACK
MOV SI,WORD PTR STKSAV+2
MOV SS,SI
;
INTEXT: POP AX ;ALL OTHERS PRODUCE ZERO RC
MOV AH,90H ;SIMULATE BUSY/SELECTED
POP DI
POP SI
POP DX
POP CX
POP BX
POP DS
IRET
;
; ADD CHARACTER TO PRINT BUFFER
;
PRNT: CMP BYTE PTR FLAG,0 ;MAKE SURE A FILE IS AVAIL.
JZ INTEXT
PUSH AX
CMP WORD PTR LEFT,BUFSIZ ;BUFFER FULL?
JNE INTADD ;NO
CALL FLUSH ;YES, FLUSH BUFFER
INTADD: POP AX
MOV BX,WORD PTR LEFT
ADD BX,OFFSET PGM:BUFFER
MOV [BX],AL ;MOVE BYTE TO BUFFER
INC WORD PTR LEFT
RET: RET ;DONE FOR NOW
;
; FLUSH PRINT BUFFER TO DISK FILE
;
FLUSH: XOR AX,AX
CMP AX,WORD PTR DS:LEFT ;BUFFER NON-EMPTY?
JE RET ;EMPTY, SKIP IT
MOV WORD PTR DS:LEFT,AX ;ELSE, RESET IT
;
PUSH ES
PUSH DS
;
; EL KLUDGEO: PRESERVE A CHUNK OF DOS 2.0 ACROSS INT 21H
;
MOV AX,DS ;COPY TO MY SEGMENT
MOV ES,AX
MOV AX,DS:STKSAV+2 ;COPYING FROM CALLER'S STACK
MOV DS,AX
MOV SI,0 ;MAGIC OFFSET TO DOS'S STACK
MOV DI,(OFFSET PGM:DOSSTK)
MOV CX,0C80H ;LENGTH TO SAVE
CLD
REP MOVSB ;COPY DOS'S STACK
POP DS
PUSH DS
;
MOV AH,GETDMA
INT 21H
PUSH ES ;SAVE OLD DMA ADDR
PUSH BX
MOV DX,OFFSET PGM:BUFFER
MOV AH,SETDMA
INT 21H ;SET UP MY DMA
MOV DX,OFFSET PGM:FCB
MOV AH,OPEN
INT 21H ;REOPEN FILE
;
MOV AX,WORD PTR DS:CURREC
MOV WORD PTR DS:FCB+33,AX ;SET NEW RECORD TO WRITE
MOV WORD PTR DS:FCB+14,BUFSIZ ;AND RECORD SIZE
MOV DX,OFFSET PGM:FCB
MOV AH,WRITER
INT 21H ;WRITE BUFFER TO DISK
OR AL,BYTE PTR DS:SAVE ;SAVE RC
MOV BYTE PTR DS:SAVE,AL
INC WORD PTR DS:CURREC ;NEXT RECORD NEXT TIME
;
MOV DX,OFFSET PGM:FCB
MOV AH,CLOSE
INT 21H ;CLOSE THE FILE TO FLUSH BUFFS
POP DX
POP DS
MOV AH,SETDMA ;RESTORE OLD DMA
INT 21H
;
POP DS
POP ES
;
CMP BYTE PTR DS:SAVE,'0' ;DID IT WORK?
JNE IOERR
;
FLHOUT: MOV AX,DS:STKSAV+2 ;COPYING TO DOS'S WORKAREA
CMP AX,100H
JA FRET ;MUST BE DOS'S SEGMENT
PUSH ES
MOV ES,AX
MOV DI,0 ;RESTORE DATA AREAS
MOV SI,(OFFSET PGM:DOSSTK)
MOV CX,0C80H ;LENGTH TO RESTORE
CLD
REP MOVSB ;COPY DOS'S STACK
POP ES ;RESTORE ES
FRET: RET
;
IOERR: XOR AX,AX
INT 10H ;CLEAR SCREEN
MOV SI,(OFFSET PGM:MSGERR)
MSGLP: MOV AL,[SI] ;GET NEXT CHARACTER
CMP AL,'$' ;END OF MESSAGE?
JE IOEOUT
XOR BX,BX ;NO...
MOV AH,14
INT 10H ;WRITE CHARACTER
INC SI
JMP MSGLP
IOEOUT: MOV BYTE PTR DS:FLAG,0 ;MARK FILE CLOSED
JMP FLHOUT
;
; PERMANENT DATA AREA (ALWAYS USE DS: FROM CODE BELOW)
;
FLAG DB 0 ;FILE OPEN FLAG
FCB DB 37 DUP(0) ;FILE CONTROL BLOCK
MSGERR DB BELL,BELL,BELL,'SPOOL WRITE ERROR - '
SAVE DB '0$'
VEC DD 0 ;OLD PRINT INT HANDLER
LEFT DW 0 ;BYTES LEFT IN DMA BUFFER
CURREC DW 0 ;CURRENT RECORD TO WRITE
BUFFER DB BUFSIZ DUP(?) ;WRITE BUFFER
DOSSTK DB 0C80H DUP(?) ;PLACE TO SAVE INT 21H'S STACK
STKSAV DD 0 ;CALLER'S STACK EA
DB 64 DUP('STACK ')
STK EQU THIS BYTE
;
; SEE IF A FILE IS ALREADY OPEN
;
INIT: CALL CHKVEC ;FIND PREVIOUS WORKAREA
CMP BYTE PTR DS:FLAG,0 ;FILE OPEN OR CLOSED?
JE NOCLS ;CLOSED, NO CLOSE NEEDED
MOV AL,1AH
MOV WORD PTR DS:STKSAV+2,AX ;MAKE SURE WE DON'T RESTORE STUFF
CALL PRNT ;PRINT END OF FILE MARK
CALL FLUSH ;FLUSH OUT WRITE BUFFER
MOV BYTE PTR DS:FLAG,0 ;NO LONGER OPEN
;
; COPY NEW FCB1 TO PERMANENT FCB
;
NOCLS: CMP BYTE PTR ES:FCB1+1,20H ;BLANK FILENAME?
JE INSTAL ;THEN DON'T OPEN IT
MOV SI,(OFFSET PGM:FCB1)
MOV DI,(OFFSET PGM:FCB)
MOV CX,35 ;LENGTH OF AN FCB
PUSH ES
PUSH DS
POP ES ;SWAP SEGMENTS
POP DS
CLD
REP MOVSB ;MOVE IT
PUSH ES
PUSH DS
POP ES
POP DS ;SWAP SEGMENTS BACK
;
; OPEN NEW FCB
;
MOV DX,(OFFSET PGM:FCB)
MOV AH,DELETE
INT 21H ;DELETE OLD FILE
MOV DX,(OFFSET PGM:FCB)
MOV AH,MAKE
INT 21H ;CREATE IT
CMP AL,0FFH
JNE ITSOPN ;ALL WENT WELL?
MOV DX,(OFFSET PGM:MSGOPN)
MOV AH,PRINT
INT 21H ;'OPEN FAILED'
XOR AX,AX
INT 21H ;TERMINATE
;
; SET UP OPEN FILE, CLEAR BUFFER
;
ITSOPN: MOV BYTE PTR DS:FLAG,0FFH ;MARK FILE AS OPEN
MOV WORD PTR DS:CURREC,0 ;RESET CURRENT RECORD
MOV WORD PTR DS:LEFT,0 ;NOTHING IN WRITE BUFFER NOW
;
MOV AH,CLOSE
MOV DX,(OFFSET PGM:FCB)
INT 21H ;CLOSE FILE UNTIL WE NEED IT
;
; INSTALL PRINT INTERCEPT IF NECESSARY
;
INSTAL: CALL CHKVEC ;IS ONE ALREADY INSTALLED?
JE EXIT ;YES, NOTHING ELSE TO DO
PUSH DS
XOR AX,AX
MOV DS,AX
MOV AX,WORD PTR DS:005CH ;SAVE OLD VECTOR
MOV WORD PTR CS:VEC,AX
MOV AX,WORD PTR DS:005EH
MOV WORD PTR CS:VEC+2,AX
MOV AX,(OFFSET PGM:INTENT)
MOV WORD PTR DS:005CH,AX ;INSTALL PARALLEL INT
MOV AX,CS
MOV WORD PTR DS:005EH,AX
POP DS
;
MOV DX,OFFSET PGM:MSG
MOV AH,PRINT
INT 21H ;'SPOOL INSTALLED'
;
; EXIT LEAVING ME IN MEMORY
;
MOV DX,OFFSET PGM:INIT
INT 27H ;EXIT BUT STAY RESIDENT
;
; EXIT NORMALLY
;
EXIT: MOV AX,CS ;PUT BACK SEGMENT
MOV DS,AX
XOR AX,AX
INT 21H ;EXIT COMPLETELY
;
; CHECK PARALLEL PRINTER VECTOR FOR INTERCEPT
;
CHKVEC: XOR AX,AX ;CHECK INT VECTORS
MOV DS,AX ;FOR PARALLEL PRINTER
MOV AX,WORD PTR DS:005CH ;GET OFFSET PART
CMP AX,(OFFSET PGM:INTENT) ;SAME AS MY INTERCEPT'S
JE SETES ;IF SO, USE OLD COPY
MOV AX,CS ;RESTORE DS REG
MOV DS,AX
RET
SETES: MOV AX,WORD PTR DS:005EH ;GET SEGMENT OF OTHER ME
MOV DS,AX ;AND USE IT INSTEAD
RET ; CS: AND ES: REMAIN THE SAME
;
CSEG ENDS
END